package com.sb.framework.exception.handler;

import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.Date;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger;
import org.springframework.ui.ModelMap;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
import com.alibaba.fastjson.JSONObject;
import com.itextpdf.text.SpecialSymbol;
import com.sb.framework.bean.RespResult;
import com.sb.framework.bean.RestStatus;
import com.sb.framework.exception.BusinessException;
import com.sb.framework.util.DateUtils;
import com.sb.framework.util.LogUtil;
import com.sb.framework.util.PathUtil;
import com.sb.framework.util.ResponseUtils;

public class SystemExceptionHandler implements HandlerExceptionResolver {
	
	private static final String	DATA_FORMAT	= DateUtils.dateTimePattern;
	
	private static final String	LOG_NAME	= "sys_err.log";
	
	/**
	 * 系统错误日记记录文件路径
	 */
	private String errLogPath = null;
	
	/**
	 * 异常时返回web页面时的，模板目录
	 */
	private String errorViewName = null;
	
	/**
	 * 错误信息在模板中的key
	 */
	private String errMessageName = null;
	
	/**
	 * 错误编码在模板中的key
	 */
	private String errCodeName = null;
	
	private Logger logger = Logger.getLogger( SystemExceptionHandler.class );

	@Override
	public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object o, Exception exception) {
		System.out.println("***********");
		ModelAndView mv = new ModelAndView();
		if (!(request.getHeader("accept").indexOf("application/json") > -1
				|| (request.getHeader("X-Requested-With") != null
						&& request.getHeader("X-Requested-With").indexOf("XMLHttpRequest") > -1))) {
			// web 返回
			String code = "errCode";
			String msg = "errMessage";
			if(errorViewName == null || "".equals(errorViewName)){
				//System.out.println("*****web return null******");
				logger.error( "errorViewName is not setting!" );
				return null;
			}
			if(errCodeName != null && !"".equals(errCodeName)){
				code = errCodeName; 
			}
			if(errMessageName != null && !"".equals(errMessageName)){
				msg = errMessageName;
			}
			mv.setViewName(errorViewName);
			ModelMap map =  mv.getModelMap();
			if (exception instanceof BusinessException) {
				//BusinessException
				BusinessException ex = (BusinessException) exception;
				logger.debug("业务异常：",ex);
				log(exception);
				map.put(code, ex.getCode());
				map.put(msg,  ex.getMessage());
			}else{
				//systemException
				logger.error("系统异常：",exception);
				log(exception);
				map.put(code, RestStatus.CODE_500);
				map.put(msg, RestStatus.CODE_500_MSG);
			}
			return mv;
		} else {
			// JSON格式返回
			if (exception instanceof BusinessException) {
				BusinessException ex = (BusinessException) exception;
				logger.debug("业务异常：",ex);
				log(exception);
				String resultStr = JSONObject.toJSONString( RespResult.buildErrorResult( ex.getCode(), ex.getMessage() ) );
				ResponseUtils.renderJson( response, resultStr );
				return mv;
			}
			logger.error("系统异常：",exception);
			log(exception);
			String resultStr = JSONObject.toJSONString( RespResult.buildErrorResult( RestStatus.CODE_500, RestStatus.CODE_500_MSG ) );
			ResponseUtils.renderJson( response, resultStr );
			return mv;
		}
		//返回null是相当于没处理
		//return null;
	}
	
	/**
	 * 日记记录
	 * @param exception
	 */
	public void log( Exception exception) {
		String time = DateUtils.formatDate( DATA_FORMAT, new Date() );
		String path = null;
		if(errLogPath != null && !"".equals(errLogPath)){
			path = errLogPath;
		}else{
			 path = PathUtil.getWebPath() + "log" + File.separator;
			File fDirectory = new File( path );
			if (!fDirectory.exists()) {
				fDirectory.mkdirs();
			}
			path = path + LOG_NAME;
		}
		System.out.println("path="+path);
		Path path2 = Paths.get(path);
		try(BufferedWriter writer= Files.newBufferedWriter(path2, Charset.forName("utf-8"),StandardOpenOption.CREATE,StandardOpenOption.APPEND);){
            writer.write(LogUtil.getErrorContent(exception, time));
		} catch (IOException e) {
			logger.error("系统异常日记记录异常：",e);
		}
	}

	public String getErrLogPath() {
		return errLogPath;
	}

	public String getErrorViewName() {
		return errorViewName;
	}

	public String getErrMessageName() {
		return errMessageName;
	}

	public String getErrCodeName() {
		return errCodeName;
	}

	public void setErrLogPath(String errLogPath) {
		this.errLogPath = errLogPath;
	}

	public void setErrorViewName(String errorViewName) {
		this.errorViewName = errorViewName;
	}

	public void setErrMessageName(String errMessageName) {
		this.errMessageName = errMessageName;
	}

	public void setErrCodeName(String errCodeName) {
		this.errCodeName = errCodeName;
	}
	
	
}
